home *** CD-ROM | disk | FTP | other *** search
- //---------------------------------------------------------------------------
- #include <vcl\vcl.h>
- #pragma hdrstop
-
- #include "CHESSBRD.H"
- #include "CHTHREAD.H"
-
-
- // Invokes the thread at once
- __fastcall ChessThread::ChessThread(char *position, bool *whitetomove,
- Square *enpassant, CastleSet *castling, bool *thinking,
- int *searchdepth, MoveFunc move) : TThread(false)
- {
- StopThinkingNow=FALSE;
- Thinking=thinking;
- Position=position;
- WhiteToMove=whitetomove;
- EnPassant=enpassant;
- Castling=castling;
- SearchDepth=searchdepth;
- Move=move;
-
- InitValues();
- }
-
- //---------------------------------------------------------------------------
- void __fastcall ChessThread::Execute()
- {
- int i;
- int v;
-
- // Should use WaitForSingleObject(...) - but how ?
- for (;;)
- {
- if (Terminated) break;
-
- if (*Thinking==TRUE)
- {
- for(int r=0;r<64;r++)
- {
- v=ColorOfPiece((Square)(r+1));
- if (v==Black) color[r]=DARK;
- else if (v==White) color[r]=LIGHT;
- else color[r]=EMPTY;
-
- switch (Position[r+1])
- {
- case 'P':
- case 'p':{piece[r]=PAWN; break;}
- case 'N':
- case 'n':{piece[r]=KNIGHT;break;}
- case 'B':
- case 'b':{piece[r]=BISHOP;break;}
- case 'R':
- case 'r':{piece[r]=ROOK; break;}
- case 'Q':
- case 'q':{piece[r]=QUEEN; break;}
- case 'K':
- case 'k':{piece[r]=KING; break;}
- default: {piece[r]=EMPTY; break;}
- }
- }
-
- if (*WhiteToMove)
- {
- side=LIGHT;
- xside=DARK;
- }
- else
- {
- side=DARK;
- xside=LIGHT;
- }
-
- castle=0;
- if (Castling->Contains(WhiteKingSide))
- castle|=1;
- if (Castling->Contains(WhiteQueenSide))
- castle|=2;
- if (Castling->Contains(BlackKingSide))
- castle|=4;
- if (Castling->Contains(BlackQueenSide))
- castle|=8;
-
- ep=*EnPassant-1;
- fifty=0;
- ply=0;
- gen_begin[0]=0;
-
- nodes=0;
- init_eval();
- memset(history,0,sizeof(history));
-
- follow_pv=TRUE;
-
- for(i=1;i<=*SearchDepth;i++)
- {
- follow_pv=TRUE;
- search(-10000,10000,i);
- if (StopThinkingNow) break;
- }
-
- if (StopThinkingNow)
- {
- *Thinking=FALSE;
- }
- else
- {
- makemove(pv[0][0].b);
- gen();
- Synchronize(PerformMove);
- }
- }
- }
-
- WaitFor();
- }
-
- void __fastcall ChessThread::CancelThinking(void)
- {
- StopThinkingNow=TRUE;
- while (*Thinking) {} //Think
- StopThinkingNow=FALSE;
- }
-
- // Synchronizer - Modifies VCL
- void __fastcall ChessThread::PerformMove(void)
- {
- if (Terminated) WaitFor();
-
- //Move expects *Thinking to be FALSE
- *Thinking=FALSE;
- if (Move (Square(pv[0][0].b.from+1),Square(pv[0][0].b.to+1))==FALSE)
- {
- Application->MessageBox("Engine tried to perform Illegal Move","Error",IDOK);
- WaitFor();
- }
- }
-
- //-------------------------------------------------------------------------
-
-
- void __fastcall ChessThread::IntCopy (int *dest, const int *source, int count)
- {
- const int *org=source;
- if (dest==NULL || source==NULL) return;
- for (;source<(org+count);source++,dest++)
- {
- *dest=*source;
- }
-
- return;
- }
-
-
- int __fastcall ChessThread::ColorOfPiece (Square sq)
- {
- if ((Position[sq]>='b')&&(Position[sq]<='r')) return Black;
- else if ((Position[sq]>='B')&&(Position[sq]<='R')) return White;
- else return NoPiece;
- }
-
- /* sort_pv() is called when the search function is following
- the PV (Principal Variation). It looks through the current
- ply's move list to see if the PV move is there. If so,
- it adds 10,000,000 to the move's score so it's played first
- by the search function. If not, follow_pv remains FALSE and
- search() stops calling sort_pv(). */
-
- void __fastcall ChessThread::sort_pv(void)
- {
- int i;
-
- follow_pv=FALSE;
- for(i=gen_begin[ply];i<gen_end[ply];i++)
- if(gen_dat[i].m.i==pv[0][ply].i) {
- follow_pv=TRUE;
- gen_dat[i].score+=10000000;
- return;
- }
- }
-
-
- /* sort() searches the current ply's move list from 'from'
- to the end to find the move with the highest score. Then it
- swaps that move and the 'from' move so the move with the
- highest score gets searched next, and hopefully produces
- a cutoff. */
-
- void __fastcall ChessThread::sort(int from)
- {
- int i;
- int bs; /* best score */
- int bi; /* best i */
- gen_rec g;
-
- bs=-1;
- for(i=from;i<gen_end[ply];i++)
- if(gen_dat[i].score>bs) {
- bs=gen_dat[i].score;
- bi=i;
- }
- g=gen_dat[from];
- gen_dat[from]=gen_dat[bi];
- gen_dat[bi]=g;
- }
-
-
- /* quiesce() is a recursive minimax search function with
- alpha-beta cutoffs. In other words, negamax. It basically
- only searches capture sequences and allows the evaluation
- function to cut the search off (and set alpha). The idea
- is to find a position where there isn't a lot going on
- so the static evaluation function will work. */
-
- int __fastcall ChessThread::quiesce(int alpha,int beta)
- {
- int i,j,x;
- BOOL c; /* in check */
- BOOL f; /* legal move found */
-
- nodes++;
- pv_length[ply]=ply;
- c=in_check(side);
-
- /* if we're in check, try all moves to get out. (not
- necessary, just something I decided to do) */
- if(c)
- gen();
-
- /* otherwise, use the evaluation function. */
- else {
- x=eval();
- if(x>=beta)
- return(beta);
- if(x>alpha)
- alpha=x;
- gen_caps();
- }
- if(follow_pv) /* are we following the PV? */
- sort_pv();
- f=FALSE;
-
- /* loop through the moves */
- for(i=gen_begin[ply];i<gen_end[ply];i++) {
- sort(i);
- if(!makemove(gen_dat[i].m.b))
- continue;
- f=TRUE; /* we found a legal move! */
- x=-quiesce(-beta,-alpha);
- takeback();
- if(x>alpha) {
- if(x>=beta)
- return(beta);
- alpha=x;
-
- /* update the PV */
- pv[ply][ply]=gen_dat[i].m;
- for(j=ply+1;j<pv_length[ply+1];j++)
- pv[ply][j]=pv[ply+1][j];
- pv_length[ply]=pv_length[ply+1];
- }
- }
-
- /* if we're in check and there aren't any legal moves,
- well, we lost */
- if((!f)&&c)
- return(-10000+ply);
- return(alpha);
- }
-
-
- /* search() does just that, in negamax fashion */
-
- int __fastcall ChessThread::search(int alpha,int beta,int depth)
- {
- int i,j,x;
- BOOL c,f;
-
- /* we're as deep as we want to be; call quiesce() to get
- a reasonable score and return it. */
- if(!depth)
- return(quiesce(alpha,beta));
- nodes++;
- pv_length[ply]=ply;
-
- /* are we in check? if so, we want to search deeper */
- c=in_check(side);
- if(c)
- depth++;
- gen();
- if(follow_pv) /* are we following the PV? */
- sort_pv();
- f=FALSE;
-
- /* loop through the moves */
- for(i=gen_begin[ply];i<gen_end[ply];i++) {
- sort(i);
- if(!makemove(gen_dat[i].m.b))
- continue;
-
- //
- if (StopThinkingNow) return -1;
-
- f=TRUE;
- x=-search(-beta,-alpha,depth-1);
- takeback();
- if(x>alpha) {
-
- /* this move caused a cutoff, so increase the history
- value so it gets ordered high next time we can
- search it */
- history[gen_dat[i].m.b.from][gen_dat[i].m.b.to]+=depth;
- if(x>=beta)
- return(beta);
- alpha=x;
-
- /* update the PV */
- pv[ply][ply]=gen_dat[i].m;
- for(j=ply+1;j<pv_length[ply+1];j++)
- pv[ply][j]=pv[ply+1][j];
- pv_length[ply]=pv_length[ply+1];
- }
- }
-
- /* no legal moves? then we're in checkmate or stalemate */
- if(!f) {
- if(c)
- return(-10000+ply);
- else
- return(0);
- }
-
- /* fifty move draw rule */
- if(fifty>100)
- return(0);
- return(alpha);
- }
-
-
- /* think() calls search() iteratively and prints the results
- after every iteration. */
-
- void __fastcall ChessThread::think(void)
- {
- int i,j,x;
-
- ply=0;
- nodes=0;
- init_eval();
- memset(history,0,sizeof(history));
- printf("ply nodes score pv\n");
- for(i=1;i<=4;i++) {
- follow_pv=TRUE;
- x=search(-10000,10000,i);
- printf("%3d %9d %5d ",i,nodes,x);
- for(j=0;j<pv_length[0];j++)
- {
- printf(" %c%d%c%d",
- FILE(pv[0][j].b.from)+'a',
- 8-RANK(pv[0][j].b.from),
- FILE(pv[0][j].b.to)+'a',
- 8-RANK(pv[0][j].b.to));
- }
- printf("\n");
- }
- }
-
- /* init() sets the board to the initial game state */
-
- void __fastcall ChessThread::init(void)
- {
- int i;
-
- for(i=0;i<64;i++) {
- color[i]=init_color[i];
- piece[i]=init_piece[i];
- }
- side=LIGHT;
- xside=DARK;
- castle=15;
- ep=-1;
- fifty=0;
- ply=0;
- gen_begin[0]=0;
- }
-
-
- /* in_check() returns TRUE if side s is in check and FALSE
- otherwise. It just scans the board to find side s's king
- and calls attack() to see if it's being attacked. */
-
- BOOL __fastcall ChessThread::in_check(int s)
- {
- int i;
-
- for(i=0;i<64;i++)
- if(color[i]==s&&piece[i]==KING)
- return(attack(i,s^1));
- return FALSE;
- }
-
-
- /* attack returns TRUE if square sq is being attacked by side
- s and FALSE otherwise. */
-
- BOOL __fastcall ChessThread::attack(int sq,int s)
- {
- int i,j,n;
-
- for(i=0;i<64;i++)
- if(color[i]==s) {
- if(piece[i]==PAWN) {
- if(s==LIGHT) {
- if(FILE(i)!=0&&i-9==sq)
- return(TRUE);
- if(FILE(i)!=7&&i-7==sq)
- return(TRUE);
- }
- else {
- if(FILE(i)!=0&&i+7==sq)
- return(TRUE);
- if(FILE(i)!=7&&i+9==sq)
- return(TRUE);
- }
- }
- else
- for(j=0;j<offsets[piece[i]];j++)
- for(n=i;;) {
- n=mailbox[mailbox64[n]+offset[piece[i]][j]];
- if(n==-1)
- break;
- if(n==sq)
- return(TRUE);
- if(color[n]!=EMPTY)
- break;
- if(!slide[piece[i]])
- break;
- }
- }
- return(FALSE);
- }
-
-
- /* gen() generates pseudo-legal moves for the current position.
- It scans the board to find friendly pieces and then determines
- what squares they attack. When it finds a piece/square
- combination, it calls gen_push to put the move on the "move
- stack." */
-
- void __fastcall ChessThread::gen(void)
- {
- int i,j,n;
-
- /* so far, we have no moves for the current ply */
- gen_end[ply]=gen_begin[ply];
- for(i=0;i<64;i++)
- if(color[i]==side) {
- if(piece[i]==PAWN) {
- if(side==LIGHT) {
- if(FILE(i)!=0&&color[i-9]==DARK)
- gen_push(i,i-9,17);
- if(FILE(i)!=7&&color[i-7]==DARK)
- gen_push(i,i-7,17);
- if(color[i-8]==EMPTY) {
- gen_push(i,i-8,16);
- if(i>=48&&color[i-16]==EMPTY)
- gen_push(i,i-16,24);
- }
- }
- else {
- if(FILE(i)!=0&&color[i+7]==LIGHT)
- gen_push(i,i+7,17);
- if(FILE(i)!=7&&color[i+9]==LIGHT)
- gen_push(i,i+9,17);
- if(color[i+8]==EMPTY) {
- gen_push(i,i+8,16);
- if(i<=15&&color[i+16]==EMPTY)
- gen_push(i,i+16,24);
- }
- }
- }
- else
- for(j=0;j<offsets[piece[i]];j++)
- for(n=i;;) {
- n=mailbox[mailbox64[n]+offset[piece[i]][j]];
- if(n==-1)
- break;
- if(color[n]!=EMPTY) {
- if(color[n]==xside)
- gen_push(i,n,1);
- break;
- }
- gen_push(i,n,0);
- if(!slide[piece[i]])
- break;
- }
- }
-
- /* generate castle moves */
- if(side==LIGHT) {
- if(castle&1)
- gen_push(60,62,2);
- if(castle&2)
- gen_push(60,58,2);
- }
- else {
- if(castle&4)
- gen_push(4,6,2);
- if(castle&8)
- gen_push(4,2,2);
- }
-
- /* generate en passant moves */
- if(ep!=-1) {
- if(side==LIGHT) {
- if(FILE(ep)!=0&&color[ep+7]==LIGHT&&piece[ep+7]==PAWN)
- gen_push(ep+7,ep,21);
- if(FILE(ep)!=7&&color[ep+9]==LIGHT&&piece[ep+9]==PAWN)
- gen_push(ep+9,ep,21);
- }
- else {
- if(FILE(ep)!=0&&color[ep-9]==DARK&&piece[ep-9]==PAWN)
- gen_push(ep-9,ep,21);
- if(FILE(ep)!=7&&color[ep-7]==DARK&&piece[ep-7]==PAWN)
- gen_push(ep-7,ep,21);
- }
- }
-
- /* the next ply's moves need to start where the current
- ply's end */
- gen_begin[ply+1]=gen_end[ply];
- }
-
-
- /* gen_caps() is basically a copy of gen() that's modified to
- only generate capture and promote moves. It's used by the
- quiescence search. */
-
- void __fastcall ChessThread::gen_caps(void)
- {
- int i,j,n;
-
- gen_end[ply]=gen_begin[ply];
- for(i=0;i<64;i++)
- if(color[i]==side) {
- if(piece[i]==PAWN) {
- if(side==LIGHT) {
- if(FILE(i)!=0&&color[i-9]==DARK)
- gen_push(i,i-9,17);
- if(FILE(i)!=7&&color[i-7]==DARK)
- gen_push(i,i-7,17);
- if(i<=15&&color[i-8]==EMPTY)
- gen_push(i,i-8,16);
- }
- if(side==DARK) {
- if(FILE(i)!=0&&color[i+7]==LIGHT)
- gen_push(i,i+7,17);
- if(FILE(i)!=7&&color[i+9]==LIGHT)
- gen_push(i,i+9,17);
- if(i>=48&&color[i+8]==EMPTY)
- gen_push(i,i+8,16);
- }
- }
- else
- for(j=0;j<offsets[piece[i]];j++)
- for(n=i;;) {
- n=mailbox[mailbox64[n]+offset[piece[i]][j]];
- if(n==-1)
- break;
- if(color[n]!=EMPTY) {
- if(color[n]==xside)
- gen_push(i,n,1);
- break;
- }
- if(!slide[piece[i]])
- break;
- }
- }
- if(ep!=-1) {
- if(side==LIGHT) {
- if(FILE(ep)!=0&&color[ep+7]==LIGHT&&piece[ep+7]==PAWN)
- gen_push(ep+7,ep,21);
- if(FILE(ep)!=7&&color[ep+9]==LIGHT&&piece[ep+9]==PAWN)
- gen_push(ep+9,ep,21);
- }
- else {
- if(FILE(ep)!=0&&color[ep-9]==DARK&&piece[ep-9]==PAWN)
- gen_push(ep-9,ep,21);
- if(FILE(ep)!=7&&color[ep-7]==DARK&&piece[ep-7]==PAWN)
- gen_push(ep-7,ep,21);
- }
- }
- gen_begin[ply+1]=gen_end[ply];
- }
-
-
- /* gen_push() puts a move on the move stack, unless it's a
- pawn promotion that needs to be handled by gen_promote().
- It also assigns a score to the move for alpha-beta move
- ordering. If the move is a capture, it uses MVV/LVA
- (Most Valuable Victim/Least Valuable Attacker). Otherwise,
- it uses the move's history heuristic value. Note that
- 1,000,000 is added to a capture move's score, so it
- always gets ordered above a "normal" move. */
-
- void __fastcall ChessThread::gen_push(int from,int to,int bits)
- {
- gen_rec *g;
-
- if(bits&16) {
- if(side==LIGHT) {
- if(to<=8) {
- gen_promote(from,to,bits);
- return;
- }
- }
- else {
- if(to>=56) {
- gen_promote(from,to,bits);
- return;
- }
- }
- }
- g=&gen_dat[gen_end[ply]];
- gen_end[ply]++;
- g->m.b.from=char(from);
- g->m.b.to=char(to);
- g->m.b.promote=0;
- g->m.b.bits=char(bits);
- if(bits&1)
- g->score=1000000+(piece[to]*10)-piece[from];
- else
- g->score=history[from][to];
- }
-
-
- /* gen_promote() is just like gen_push(), only it puts 4 moves
- on the move stack, one for each possible promotion piece */
-
- void __fastcall ChessThread::gen_promote(int from,int to,int bits)
- {
- int i;
- gen_rec *g;
-
- for(i=KNIGHT;i<=QUEEN;i++) {
- g=&gen_dat[gen_end[ply]];
- gen_end[ply]++;
- g->m.b.from=char(from);
- g->m.b.to=char(to);
- g->m.b.promote=char(i);
- g->m.b.bits=char(bits|32);
- g->score=1000000+(i*10);
- }
- }
-
-
- /* makemove() makes a move. If the move is illegal, it
- undoes whatever it did and returns FALSE. Otherwise, it
- returns TRUE. */
-
- BOOL __fastcall ChessThread::makemove(move_bytes m)
- {
-
- /* test to see if a castle move is legal and move the rook
- (the king is moved with the usual move code later) */
- if(m.bits&2) {
- if(in_check(side))
- return(FALSE);
- switch(m.to) {
- case 62:
- if(color[61]!=EMPTY||color[62]!=EMPTY||
- attack(61,xside)||attack(62,xside))
- return(FALSE);
- color[61]=LIGHT;
- piece[61]=ROOK;
- color[63]=EMPTY;
- piece[63]=EMPTY;
- break;
- case 58:
- if(color[57]!=EMPTY||color[58]!=EMPTY||color[59]!=EMPTY||
- attack(58,xside)||attack(59,xside))
- return(FALSE);
- color[59]=LIGHT;
- piece[59]=ROOK;
- color[56]=EMPTY;
- piece[56]=EMPTY;
- break;
- case 6:
- if(color[5]!=EMPTY||color[6]!=EMPTY||
- attack(5,xside)||attack(6,xside))
- return(FALSE);
- color[5]=DARK;
- piece[5]=ROOK;
- color[7]=EMPTY;
- piece[7]=EMPTY;
- break;
- case 2:
- if(color[1]!=EMPTY||color[2]!=EMPTY||color[3]!=EMPTY||
- attack(2,xside)||attack(3,xside))
- return(FALSE);
- color[3]=DARK;
- piece[3]=ROOK;
- color[0]=EMPTY;
- piece[0]=EMPTY;
- break;
- }
- }
-
- /* back up information so we can take the move back later. */
- hist_dat[ply].m.b=m;
- hist_dat[ply].capture=piece[m.to];
- hist_dat[ply].castle=castle;
- hist_dat[ply].ep=ep;
- hist_dat[ply].fifty=fifty;
- ply++;
-
- /* update the castle, en passant, and
- fifty-move-draw variables */
- castle&=castle_mask[m.from]&castle_mask[m.to];
- if(m.bits&8) {
- if(side==LIGHT)
- ep=m.to+8;
- else
- ep=m.to-8;
- }
- else
- ep=-1;
- if(m.bits&17)
- fifty=0;
- else
- fifty++;
-
- /* move the piece */
- color[m.to]=side;
- if(m.bits&32)
- piece[m.to]=m.promote;
- else
- piece[m.to]=piece[m.from];
- color[m.from]=EMPTY;
- piece[m.from]=EMPTY;
-
- /* erase the pawn if this is an en passant move */
- if(m.bits&4) {
- if(side==LIGHT) {
- color[m.to+8]=EMPTY;
- piece[m.to+8]=EMPTY;
- }
- else {
- color[m.to-8]=EMPTY;
- piece[m.to-8]=EMPTY;
- }
- }
-
- /* switch sides and test for legality (if we can capture
- the other guy's king, it's an illegal position and
- we need to take the move back) */
- side^=1;
- xside^=1;
- if(in_check(xside)) {
- takeback();
- return(FALSE);
- }
- return(TRUE);
- }
-
-
- /* takeback() is very similar to makemove(), only backwards :) */
-
- void __fastcall ChessThread::takeback(void)
- {
- move_bytes m;
-
- side^=1;
- xside^=1;
- ply--;
- m=hist_dat[ply].m.b;
- castle=hist_dat[ply].castle;
- ep=hist_dat[ply].ep;
- fifty=hist_dat[ply].fifty;
- color[m.from]=side;
- if(m.bits&32)
- piece[m.from]=PAWN;
- else
- piece[m.from]=piece[m.to];
- if(hist_dat[ply].capture==EMPTY) {
- color[m.to]=EMPTY;
- piece[m.to]=EMPTY;
- }
- else {
- color[m.to]=xside;
- piece[m.to]=hist_dat[ply].capture;
- }
- if(m.bits&2) {
- int from,to;
-
- switch(m.to) {
- case 62: from=61; to=63; break;
- case 58: from=59; to=56; break;
- case 6: from=5; to=7; break;
- case 2: from=3; to=0; break;
- }
- color[to]=side;
- piece[to]=ROOK;
- color[from]=EMPTY;
- piece[from]=EMPTY;
- }
- if(m.bits&4) {
- if(side==LIGHT) {
- color[m.to+8]=xside;
- piece[m.to+8]=PAWN;
- }
- else {
- color[m.to-8]=xside;
- piece[m.to-8]=PAWN;
- }
- }
- }
-
- int __fastcall ChessThread::eval(void)
- {
- int i;
- int c; /* color */
- int xc; /* not c */
- int f; /* file */
- int score[2]; /* the score for each side */
- int pawns[2][10]; /* the number of pawns of each color on each file */
-
- score[LIGHT]=score[DARK]=0;
- memset(pawns,0,sizeof(pawns));
-
- /* loop through to set up the pawns array and to add up the
- piece/square table values for each piece. */
- for(i=0;i<64;i++) {
- if(color[i]==EMPTY)
- continue;
- if(piece[i]==PAWN)
- pawns[color[i]][FILE(i)+1]++;
- score[color[i]]+=pcsq[color[i]][piece[i]][i];
- }
-
- /* now that we have the pawns array set up, evaluate the pawns
- and rooks */
- for(i=0;i<64;i++) {
- if(color[i]==EMPTY)
- continue;
- c=color[i]; /* set up c, xc, and f so we don't have to type a lot */
- xc=c^1;
- f=FILE(i)+1;
- if(piece[i]==PAWN) {
- if(pawns[c][f]>1) /* this pawn is doubled */
- score[c]-=5;
- if((!pawns[c][f-1])&&
- (!pawns[c][f+1])) { /* isolated */
- score[c]-=20;
- if(!pawns[xc][f])
- score[c]-=10;
- }
- if((!pawns[xc][f-1])&& /* passed */
- (!pawns[xc][f])&&
- (!pawns[xc][f+1]))
- score[c]+=2*pcsq[c][PAWN][i];
- }
- if(piece[i]==ROOK)
- if(!pawns[c][f]) { /* the rook is on a half-open file */
- score[c]+=10;
- if(!pawns[xc][f]) /* actually, it's totally open */
- score[c]+=5;
- }
- }
-
- /* return the score relative to the side to move (i.e.,
- a positive score means the side to move is winning) */
- if(side==LIGHT)
- return(score[LIGHT]-score[DARK]);
- return(score[DARK]-score[LIGHT]);
- }
-
- void __fastcall ChessThread::init_eval(void)
- {
- int i,material,king_sq;
-
- memset(pcsq,0,sizeof(pcsq));
-
- /* initialize the no-brainer piece/square tables */
- for(i=0;i<64;i++) {
- pcsq[LIGHT][PAWN][i]=value[PAWN]+pawn_pcsq[i];
- pcsq[LIGHT][KNIGHT][i]=value[KNIGHT]+minor_pcsq[i];
- pcsq[LIGHT][BISHOP][i]=value[BISHOP]+minor_pcsq[i];
- pcsq[LIGHT][ROOK][i]=value[ROOK];
- pcsq[LIGHT][QUEEN][i]=value[QUEEN];
- pcsq[DARK][PAWN][i]=value[PAWN]+pawn_pcsq[flip[i]];
- pcsq[DARK][KNIGHT][i]=value[KNIGHT]+minor_pcsq[flip[i]];
- pcsq[DARK][BISHOP][i]=value[BISHOP]+minor_pcsq[flip[i]];
- pcsq[DARK][ROOK][i]=value[ROOK];
- pcsq[DARK][QUEEN][i]=value[QUEEN];
- }
-
- /* now scan the board to see how much piece material the
- enemy has and figure out what side of the board the
- king is on */
- material=0;
- for(i=0;i<64;i++) {
- if(color[i]==DARK&&piece[i]!=PAWN)
- material+=value[piece[i]];
- if(color[i]==LIGHT&&piece[i]==KING)
- king_sq=i;
- }
- if(material>1400) { /* use the middlegame tables */
- for(i=0;i<64;i++)
- pcsq[LIGHT][KING][i]=king_pcsq[i];
- if(FILE(king_sq)>=5)
- for(i=0;i<64;i++)
- pcsq[LIGHT][PAWN][i]+=kingside_pawn_pcsq[i];
- if(FILE(king_sq)<=2)
- for(i=0;i<64;i++)
- pcsq[LIGHT][PAWN][i]+=queenside_pawn_pcsq[i];
- }
- else
- for(i=0;i<64;i++)
- pcsq[LIGHT][KING][i]=endgame_king_pcsq[i];
-
- /* do the same for black */
- material=0;
- for(i=0;i<64;i++) {
- if(color[i]==LIGHT&&piece[i]!=PAWN)
- material+=value[piece[i]];
- if(color[i]==DARK&&piece[i]==KING)
- king_sq=i;
- }
- if(material>1400) {
- for(i=0;i<64;i++)
- pcsq[DARK][KING][i]=king_pcsq[flip[i]];
- if(FILE(king_sq)>=5)
- for(i=0;i<64;i++)
- pcsq[DARK][PAWN][i]+=kingside_pawn_pcsq[flip[i]];
- if(FILE(king_sq)<=2)
- for(i=0;i<64;i++)
- pcsq[DARK][PAWN][i]+=queenside_pawn_pcsq[flip[i]];
- }
- else
- for(i=0;i<64;i++)
- pcsq[DARK][KING][i]=endgame_king_pcsq[flip[i]];
- }
-
-
- //---------------------------------------------------------------------------
- void __fastcall ChessThread::InitValues()
- {
- int _flip[64]=
- {
- 56, 57, 58, 59, 60, 61, 62, 63,
- 48, 49, 50, 51, 52, 53, 54, 55,
- 40, 41, 42, 43, 44, 45, 46, 47,
- 32, 33, 34, 35, 36, 37, 38, 39,
- 24, 25, 26, 27, 28, 29, 30, 31,
- 16, 17, 18, 19, 20, 21, 22, 23,
- 8, 9, 10, 11, 12, 13, 14, 15,
- 0, 1, 2, 3, 4, 5, 6, 7
- };
-
- IntCopy (&flip[0],&_flip[0],64);
-
- int _pawn_pcsq[64]= {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 5, 10, 15, 20, 20, 15, 10, 5,
- 4, 8, 12, 16, 16, 12, 8, 4,
- 3, 6, 9, 12, 12, 9, 6, 3,
- 2, 4, 6, 8, 8, 6, 4, 2,
- 1, 2, 3, 4, 4, 3, 2, 1,
- 0, 0, 0, -20, -20, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0
- };
-
- IntCopy (&pawn_pcsq[0],&_pawn_pcsq[0],64);
-
- int _kingside_pawn_pcsq[64]= {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 5, 5, 5,
- 0, 0, 0, 0, 0, 10, 10, 10,
- 0, 0, 0, 0, 0, 20, 20, 20,
- 0, 0, 0, 0, 0, 0, 0, 0
- };
-
- IntCopy (&kingside_pawn_pcsq[0],&_kingside_pawn_pcsq[0],64);
-
- int _queenside_pawn_pcsq[64]= {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 5, 5, 5, 0, 0, 0, 0, 0,
- 10, 10, 10, 0, 0, 0, 0, 0,
- 20, 20, 20, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0
- };
-
- IntCopy (&queenside_pawn_pcsq[0],&_queenside_pawn_pcsq[0],64);
-
- int _minor_pcsq[64]= {
- -10, -10, -10, -10, -10, -10, -10, -10,
- -10, 0, 0, 0, 0, 0, 0, -10,
- -10, 0, 5, 5, 5, 5, 0, -10,
- -10, 0, 5, 10, 10, 5, 0, -10,
- -10, 0, 5, 10, 10, 5, 0, -10,
- -10, 0, 5, 5, 5, 5, 0, -10,
- -10, 0, 0, 0, 0, 0, 0, -10,
- -20, -20, -20, -20, -20, -20, -20, -20,
- };
-
- IntCopy (&minor_pcsq[0],&_minor_pcsq[0],64);
-
- int _king_pcsq[64]= {
- -40, -40, -40, -40, -40, -40, -40, -40,
- -40, -40, -40, -40, -40, -40, -40, -40,
- -40, -40, -40, -40, -40, -40, -40, -40,
- -40, -40, -40, -40, -40, -40, -40, -40,
- -40, -40, -40, -40, -40, -40, -40, -40,
- -40, -40, -40, -40, -40, -40, -40, -40,
- -20, -20, -20, -20, -20, -20, -20, -20,
- -10, 0, 10, -20, 0, -20, 10, 0
- };
-
- IntCopy (&king_pcsq[0],&_king_pcsq[0],64);
-
- int _endgame_king_pcsq[64]= {
- -5, -5, -5, -5, -5, -5, -5, -5,
- -5, 0, 0, 0, 0, 0, 0, -5,
- -5, 0, 5, 5, 5, 5, 0, -5,
- -5, 0, 5, 10, 10, 5, 0, -5,
- -5, 0, 5, 10, 10, 5, 0, -5,
- -5, 0, 5, 5, 5, 5, 0, -5,
- -5, 0, 0, 0, 0, 0, 0, -5,
- -5, -5, -5, -5, -5, -5, -5, -5
- };
-
- IntCopy (&endgame_king_pcsq[0],&_endgame_king_pcsq[0],64);
-
-
- int _mailbox[120]= {
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, 0, 1, 2, 3, 4, 5, 6, 7, -1,
- -1, 8, 9, 10, 11, 12, 13, 14, 15, -1,
- -1, 16, 17, 18, 19, 20, 21, 22, 23, -1,
- -1, 24, 25, 26, 27, 28, 29, 30, 31, -1,
- -1, 32, 33, 34, 35, 36, 37, 38, 39, -1,
- -1, 40, 41, 42, 43, 44, 45, 46, 47, -1,
- -1, 48, 49, 50, 51, 52, 53, 54, 55, -1,
- -1, 56, 57, 58, 59, 60, 61, 62, 63, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
- };
-
- IntCopy (&mailbox[0],&_mailbox[0],120);
-
-
- int _mailbox64[64]= {
- 21, 22, 23, 24, 25, 26, 27, 28,
- 31, 32, 33, 34, 35, 36, 37, 38,
- 41, 42, 43, 44, 45, 46, 47, 48,
- 51, 52, 53, 54, 55, 56, 57, 58,
- 61, 62, 63, 64, 65, 66, 67, 68,
- 71, 72, 73, 74, 75, 76, 77, 78,
- 81, 82, 83, 84, 85, 86, 87, 88,
- 91, 92, 93, 94, 95, 96, 97, 98
- };
-
- IntCopy (&mailbox64[0],&_mailbox64[0],64);
-
- slide[0]=FALSE;
- slide[1]=FALSE;
- slide[2]=TRUE;
- slide[3]=TRUE;
- slide[4]=TRUE;
- slide[5]=FALSE;
-
- int _offsets[6]= {
- 0, 8, 4, 4, 8, 8
- };
-
- IntCopy (&offsets[0],&_offsets[0],6);
-
-
- int _offset[6][8]={
- {0, 0, 0, 0, 0, 0, 0, 0,},
- {-21, -19, -12, -8, 8, 12, 19, 21,},
- {-11, -9, 9, 11, 0, 0, 0, 0,},
- {-10, -1, 1, 10, 0, 0, 0, 0,},
- {-11, -10, -9, -1, 1, 9, 10, 11,},
- {-11, -10, -9, -1, 1, 9, 10, 11}
- };
-
- IntCopy (&offset[0][0],&_offset[0][0],48);
-
- int _castle_mask[64]= {
- 7, 15, 15, 15, 3, 15, 15, 11,
- 15, 15, 15, 15, 15, 15, 15, 15,
- 15, 15, 15, 15, 15, 15, 15, 15,
- 15, 15, 15, 15, 15, 15, 15, 15,
- 15, 15, 15, 15, 15, 15, 15, 15,
- 15, 15, 15, 15, 15, 15, 15, 15,
- 15, 15, 15, 15, 15, 15, 15, 15,
- 13, 15, 15, 15, 12, 15, 15, 14
- };
-
- IntCopy (&castle_mask[0],&_castle_mask[0],64);
-
- int _value[6]= {
- 100, 300, 300, 500, 900, 10000
- };
-
- IntCopy (&value[0],&_value[0],6);
-
- piece_char[0]='P';
- piece_char[1]='N';
- piece_char[2]='B';
- piece_char[3]='R';
- piece_char[4]='Q';
- piece_char[5]='K';
-
- int _init_color[64]= {
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 6, 6, 6, 6, 6, 6, 6, 6,
- 6, 6, 6, 6, 6, 6, 6, 6,
- 6, 6, 6, 6, 6, 6, 6, 6,
- 6, 6, 6, 6, 6, 6, 6, 6,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0
- };
-
- IntCopy (&init_color[0],&_init_color[0],64);
-
- int _init_piece[64]= {
- 3, 1, 2, 4, 5, 2, 1, 3,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 6, 6, 6, 6, 6, 6, 6, 6,
- 6, 6, 6, 6, 6, 6, 6, 6,
- 6, 6, 6, 6, 6, 6, 6, 6,
- 6, 6, 6, 6, 6, 6, 6, 6,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 3, 1, 2, 4, 5, 2, 1, 3
- };
-
- IntCopy (&init_piece[0],&_init_piece[0],64);
- }
- //-----------------------------------------------------------------------
-